package jmine.tec.utils.poi;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import jmine.tec.utils.Tuple;
import jmine.tec.utils.UnmodifiableTuple;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;

/**
 * Represents a single Spreadsheet from a Workbook.
 * 
 * @author julien
 */
public class Spreadsheet {

    private HSSFSheet sheet;

    private String nome;

    /**
     * Constructs this Spreadsheet given an input {@link HSSFSheet}
     * 
     * @param sheet {@link HSSFSheet}
     */
    public Spreadsheet(final HSSFSheet sheet) {
        this.sheet = sheet;
    }

    /**
     * Returns the String value of the cell (row, col).
     * 
     * @param row int
     * @param col int
     * @return String
     */
    public String getString(final int row, final int col) {
        HSSFRow ssrow = this.sheet.getRow(row);
        if (ssrow != null) {
            HSSFCell cell = ssrow.getCell(col);
            return (cell != null) ? cell.getRichStringCellValue().getString() : null;
        }
        return null;
    }

    /**
     * Returns the Double value of the cell (row, col).
     * 
     * @param row int
     * @param col int
     * @return Double
     */
    public Double getDouble(final int row, final int col) {
        HSSFRow ssrow = this.sheet.getRow(row);
        if (ssrow != null) {
            HSSFCell cell = ssrow.getCell(col);
            return (cell != null) ? cell.getNumericCellValue() : null;
        }
        return null;
    }

    /**
     * Returns the Date value of the cell (row, col).
     * 
     * @param row int
     * @param col int
     * @return Date
     */
    public Date getDate(final int row, final int col) {
        HSSFRow ssrow = this.sheet.getRow(row);
        if (ssrow != null) {
            HSSFCell cell = ssrow.getCell(col);
            return (cell != null) ? cell.getDateCellValue() : null;
        }
        return null;
    }

    /**
     * Returns the String value of the cell (row, col).
     * 
     * @param row int
     * @param col int
     * @return String
     */
    public Boolean getBoolean(final int row, final int col) {
        HSSFRow ssrow = this.sheet.getRow(row);
        if (ssrow != null) {
            HSSFCell cell = ssrow.getCell(col);
            return (cell != null) ? cell.getBooleanCellValue() : null;
        }
        return null;
    }

    /**
     * Returns a list of tuples date+double located between the given rows (both included).
     * 
     * @param startRow The starting row
     * @param endRow The ending row
     * @param dateCol The column with the Date values
     * @param valueCol The column with the Double values
     * @return List
     */
    public List<Tuple<Date, Double>> getSerie(final int startRow, final int endRow, final int dateCol,
            final int valueCol) {
        /**
         * Linkedlist so we garantee the order of the Tuples is preserved when the list is iterated over.
         */
        List<Tuple<Date, Double>> ret = new LinkedList<Tuple<Date, Double>>();

        for (int i = startRow; i <= endRow; i++) {
            HSSFRow row = this.sheet.getRow(i);

            Date date = row.getCell(dateCol).getDateCellValue();
            Double value = row.getCell(valueCol).getNumericCellValue();
            ret.add(UnmodifiableTuple.newTuple(date, value));
        }
        return ret;
    }

    /**
     * Returns a list of tuples date+double given the columns. Assumes values must be read from row 0 to endRow (included).
     * 
     * @param endRow int
     * @param dateCol int
     * @param valueCol int
     * @return List
     */
    public List<Tuple<Date, Double>> getSerie(final int endRow, final int dateCol, final int valueCol) {
        return this.getSerie(0, endRow, dateCol, valueCol);
    }

    /**
     * @return the nome
     */
    public String getNome() {
        return this.nome;
    }

    /**
     * @param nome the nome to set
     */
    public void setNome(final String nome) {
        this.nome = nome;
    }
}
